package com.katesoft.scale4j.rttp.subscription;

import com.katesoft.scale4j.common.annotation.ValueObject;
import com.katesoft.scale4j.common.model.IPrettyPrintableObject;
import com.katesoft.scale4j.persistent.model.unified.AbstractPersistentEntity;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.springframework.beans.factory.annotation.Required;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;

/**
 * this class allows to subscribe for domain entities events(inserts, updates).
 * <p/>
 * jvmcluster-rttp will provided multi-threaded distributed execution of business processes.
 *
 * @author kate2007
 */
@ValueObject
public class CloudSubscription<T extends AbstractPersistentEntity> implements Serializable, IPrettyPrintableObject, ICloudSubscription<T>
{
    private Class<T> subscriptionClass;
    private IUnaryPredicate<T> predicate;
    private Collection<IBusinessProcess<T>> processes;

    /**
     * specify domain entity class that should be tracked. this field is required.
     *
     * @param subscriptionClass domain class
     */
    @Required
    public void setSubscriptionClass(Class<T> subscriptionClass)
    {
        this.subscriptionClass = subscriptionClass;
    }

    /**
     * specify business predicate to be evaluated. this field is required.
     *
     * @param predicate business predicate
     */
    @Required
    public void setPredicate(IUnaryPredicate<T> predicate)
    {
        this.predicate = predicate;
    }

    /**
     * specify business processes to be executed in case of successful predicate evaluation.
     * <p/>
     * each of business processed will be wrapped with distributed(load balanced) multi threaded execution.
     *
     * @param processes collection of business processes.
     */
    @Required
    public void setProcesses(Collection<IBusinessProcess<T>> processes)
    {
        this.processes = processes;
    }

    @Override
    public Class<T> getSubscriptionClass()
    {
        return subscriptionClass;
    }

    @Override
    public IUnaryPredicate<T> getPredicate()
    {
        return predicate;
    }

    @Override
    public Collection<IBusinessProcess<T>> getProcesses()
    {
        return processes;
    }

    @Override
    public String reflectionToString()
    {
        return ReflectionToStringBuilder.reflectionToString(this);
    }

    public static <T extends AbstractPersistentEntity> ICloudSubscription<T> newInstance(IUnaryPredicate<T> predicate,
                                                                                         IBusinessProcess<T> process,
                                                                                         Class<T> clazz)
    {
        CloudSubscription<T> subscription = new CloudSubscription<T>();
        subscription.setProcesses(Collections.singleton(process));
        subscription.setPredicate(predicate);
        subscription.setSubscriptionClass(clazz);
        return subscription;
    }
}
